#include <stdio.h>
#include <stdbool.h>
#include <string.h>
#include <malloc.h>
#include <stdlib.h>

#include "interaction.h"
#include "ticket_device.h"
#include "list.h"
#include "log.h"

static int read_ticket_file(struct list_head *ticket_head);
static int write_user_ticket_file(struct list_head *user_ticket_head);
static int write_ticket_file(struct list_head *ticket_head);
static int read_user_ticket_file(struct list_head *user_ticket_head);
static void get_date(char *date);
static int compare_date(char *date1, char *date2);

/* 单次保存用户的车票数据 */
void write_user_ticket_file_onetime(struct list_head *user_ticket_head)
{
    write_user_ticket_file(user_ticket_head);
}

/* 单次保存车票数据 */
void write_ticket_file_onetime(struct list_head *ticket_head)
{
    write_ticket_file(ticket_head);
}

/**
 * @brief   车票链表初始化
 * @param   ticket_head:包含所有车票信息的指针
 *          user_ticket_head:包含所有用户的车票信息的指针
 * @return  MALLOC_ERROR:申请内存失败
 *          true:正常运行
 *          false:读取文件失败
 */
int ticket_init(struct list_head *ticket_head,
                struct list_head *user_ticket_head)
{
    int ret;
    char date[11];
    struct list_head *pos, *n, *pos2, *n2;
    struct ticket *scan_list_ticket;
    struct user_ticket *scan_list_user_ticket;

    init_list_head(ticket_head);
    init_list_head(user_ticket_head);

    /*文件操作*/
    ret = read_ticket_file(ticket_head);
    if (ret != true) {
        DEBUG("READ TICKET FILE ERROR!");
        return false;
    }

    /*删除过期车票*/
    get_date(date);
    list_for_each_safe (pos, n, ticket_head) {
        scan_list_ticket = list_entry(pos, struct ticket, list);
        if (0 == compare_date(scan_list_ticket->date, date)) {
            list_del(pos);
            free(scan_list_ticket);
        }
    }

    ret = read_user_ticket_file(user_ticket_head);
    if (ret != true) {
        DEBUG("READ TICKET FILE ERROR!");
        return false;
    }
    /*删除过期车票*/
    list_for_each_safe (pos2, n2, user_ticket_head) {
        scan_list_user_ticket = list_entry(pos2, struct user_ticket, list);
        if (0 == compare_date(scan_list_user_ticket->date, date)) {
            list_del(pos2);
            free(scan_list_user_ticket);
        }
    }

    return true;
}

/**
 * @brief   将车票数据从文件中读出来
 * @param   ticket_head：车票数据的头指针
 * @return  传参错误、打开文件错误、malloc错误等一系列错误返回false
 *          正确运行返回true
 */
static int read_ticket_file(struct list_head *ticket_head)
{
    char origin_place[ORIGIN_PLACE_SIZE];
    char destination[DESTINATION_SIZE];
    struct ticket *temp = NULL;
    FILE *save_file;

    /* 打开文件 */
    save_file = fopen("/home/ubuntu/train1/lib/ticket_data.txt", "a+");
    if (!save_file) {
        save_file = fopen("/home/ubuntu/train1/lib/ticket_data.txt", "a+");
        if (!save_file) {
            DEBUG("FAIL TO OPEN TICKET DATA FILE\n");
            return false;
        }
    }

    temp = (struct ticket *)malloc(sizeof(struct ticket));
    if (!temp) {
        DEBUG("FAIL TO MALLOC\n");
        fclose(save_file);
        return false;
    }

    /* 先把数据读取到temp里面 */
    fscanf(save_file, "%20s\t%20s\t%6s\t%6s\t%6s\t%5s\t%5s\t%5s\t%5s\t%11s\t%4s\t%4s\t%4s\t%4s",
                        origin_place, 
                        destination,
                        temp->train_number,
                        temp->departure_time,
                        temp->arrival_time,
                        temp->type1_price,
                        temp->type2_price,
                        temp->type3_price,
                        temp->type4_price,
                        temp->date,
                        temp->ticket_type1_num,
                        temp->ticket_type2_num,
                        temp->ticket_type3_num,
                        temp->ticket_type4_num);

    strncpy(temp->origin_place, origin_place, sizeof(origin_place));
    strncpy(temp->destination, destination, sizeof(destination));

    /* 将节点接入链表 */
    while (!feof(save_file)) {
        list_add_tail(&temp->list, ticket_head);

        temp = (struct ticket *)
                    malloc(sizeof(struct ticket));
        if (!temp) {
            DEBUG("FAIL TO MALLOC\n");
            return false;
        }

        fscanf(save_file, "%20s\t%20s\t%6s\t%6s\t%6s\t%5s\t%5s\t%5s\t%5s\t%11s\t%4s\t%4s\t%4s\t%4s",
                        origin_place, 
                        destination,
                        temp->train_number,
                        temp->departure_time,
                        temp->arrival_time,
                        temp->type1_price,
                        temp->type2_price,
                        temp->type3_price,
                        temp->type4_price,
                        temp->date,
                        temp->ticket_type1_num,
                        temp->ticket_type2_num,
                        temp->ticket_type3_num,
                        temp->ticket_type4_num);

        strncpy(temp->origin_place, origin_place, sizeof(origin_place));
        strncpy(temp->destination, destination, sizeof(destination));
    }

    free(temp);
    fclose(save_file);
    return true;
}

/**
 * @brief   将车票数据从文件中读出来
 * @param   ticket_head：车票数据的头指针
 * @return  传参错误、打开文件错误、malloc错误等一系列错误返回false
 *          正确运行返回true
 */
static int read_user_ticket_file(struct list_head *user_ticket_head)
{
    struct user_ticket *temp = NULL;
    FILE *save_file;

    /* 打开文件 */
    save_file = fopen("/home/ubuntu/train1/lib/user_ticket_data.txt", "a+");
    if (!save_file) {
        save_file = fopen("/home/ubuntu/train1/lib/user_ticket_data.txt", "a+");
        if (!save_file) {
            DEBUG("FAIL TO OPEN TICKET DATA FILE\n");
            return false;
        }
    }

    temp = (struct user_ticket *)malloc(sizeof(struct user_ticket));
    if (!temp) {
        DEBUG("FAIL TO MALLOC\n");
        fclose(save_file);
        return false;
    }

    /* 先把数据读取到temp里面 */
    fscanf(save_file, "%11s\t%20s\t%19s\t%12s\t%20s\t%20s\t%6s\t%6s\t%6s\t%5s\t%11s\t%20s",
                        temp->id,
                        temp->name,
                        temp->citizen_id,
                        temp->phone_num,
                        temp->origin_place, 
                        temp->destination,
                        temp->train_number,
                        temp->departure_time,
                        temp->arrival_time,
                        temp->price,
                        temp->date,
                        temp->ticket_type);

    /* 将节点接入链表 */
    while (!feof(save_file)) {
        list_add_tail(&temp->list, user_ticket_head);

        temp = (struct user_ticket *)
                    malloc(sizeof(struct user_ticket));
        if (!temp) {
            DEBUG("FAIL TO MALLOC\n");
            return false;
        }

        fscanf(save_file, "%11s\t%20s\t%19s\t%12s\t%20s\t%20s\t%6s\t%6s\t%6s\t%5s\t%11s\t%20s",
                        temp->id,
                        temp->name,
                        temp->citizen_id,
                        temp->phone_num,
                        temp->origin_place, 
                        temp->destination,
                        temp->train_number,
                        temp->departure_time,
                        temp->arrival_time,
                        temp->price,
                        temp->date,
                        temp->ticket_type);
    }

    free(temp);
    fclose(save_file);
    return true;
}

/**
 *@brife:将链表中的信息重新整理，装入ticket_buffer中
 */
int build_ticket_buffer(char *ticket_buffer, struct list_head *temporary_head)
{
    struct list_head *pos;
    struct user_ticket *scan_list;

    list_for_each (pos, temporary_head) {
        scan_list = list_entry(pos, struct user_ticket, list);

        /* 字符串拼接，为了方便安卓端分割，
        每个数据后面接|，每段数据后面接逗号，最后结尾接句号 */
        strcat(ticket_buffer, scan_list->origin_place);
        strcat(ticket_buffer, "|");
        strcat(ticket_buffer, scan_list->destination);
        strcat(ticket_buffer, "|");
        strcat(ticket_buffer, scan_list->departure_time);
        strcat(ticket_buffer, "|");
        strcat(ticket_buffer, scan_list->arrival_time);
        strcat(ticket_buffer, "|");
        strcat(ticket_buffer, scan_list->train_number);
        strcat(ticket_buffer, "|");
        strcat(ticket_buffer, scan_list->price);
        strcat(ticket_buffer, "|");
        strcat(ticket_buffer, scan_list->date);
        strcat(ticket_buffer, "|");
        strcat(ticket_buffer, scan_list->citizen_id);
        strcat(ticket_buffer, "|");
        strcat(ticket_buffer, scan_list->name);
        strcat(ticket_buffer, "|");
        strcat(ticket_buffer, scan_list->phone_num);
        strcat(ticket_buffer, "|");
        strcat(ticket_buffer, scan_list->ticket_type);
        strcat(ticket_buffer, "|");
        strcat(ticket_buffer, ",");
    }
    strcat(ticket_buffer, ".");
    return true;
}

int build_ticket_buffer_2(char *ticket_buffer, struct list_head *temporary_head)
{
    struct list_head *pos;
    struct ticket *scan_list;

    list_for_each (pos, temporary_head) {
        scan_list = list_entry(pos, struct ticket, list);

        /* 字符串拼接，为了方便安卓端分割，
        每个数据后面接|，每段数据后面接逗号，最后结尾接句号 */
        strcat(ticket_buffer, scan_list->origin_place);
        strcat(ticket_buffer, "|");
        strcat(ticket_buffer, scan_list->destination);
        strcat(ticket_buffer, "|");
        strcat(ticket_buffer, scan_list->departure_time);
        strcat(ticket_buffer, "|");
        strcat(ticket_buffer, scan_list->arrival_time);
        strcat(ticket_buffer, "|");
        strcat(ticket_buffer, scan_list->train_number);
        strcat(ticket_buffer, "|");
        strcat(ticket_buffer, scan_list->type1_price);
        strcat(ticket_buffer, "|");
        strcat(ticket_buffer, scan_list->type2_price);
        strcat(ticket_buffer, "|");
        strcat(ticket_buffer, scan_list->type3_price);
        strcat(ticket_buffer, "|");
        strcat(ticket_buffer, scan_list->type4_price);
        strcat(ticket_buffer, "|");
        strcat(ticket_buffer, scan_list->date);
        strcat(ticket_buffer, "|");
        strcat(ticket_buffer, scan_list->ticket_type1_num);
        strcat(ticket_buffer, "|");
        strcat(ticket_buffer, scan_list->ticket_type2_num);
        strcat(ticket_buffer, "|");
        strcat(ticket_buffer, scan_list->ticket_type3_num);
        strcat(ticket_buffer, "|");
        strcat(ticket_buffer, scan_list->ticket_type4_num);
        strcat(ticket_buffer, "|");
        strcat(ticket_buffer, ",");
    }
    strcat(ticket_buffer, ".");
    return true;
}

/**
 *@brife:将链表中的信息重新整理，装入ticket_buffer中
 */
int build_all_ticket_buffer(char *ticket_buffer, struct list_head *ticket_head)
{
    struct list_head *pos;
    struct ticket *scan_list;

    list_for_each (pos, ticket_head) {
        scan_list = list_entry(pos, struct ticket, list);

        /* 字符串拼接，为了方便安卓端分割，
        每个数据后面接|，每段数据后面接逗号，最后结尾接句号 */
        strcat(ticket_buffer, scan_list->origin_place);
        strcat(ticket_buffer, "|");
        strcat(ticket_buffer, scan_list->destination);
        strcat(ticket_buffer, "|");
        strcat(ticket_buffer, scan_list->departure_time);
        strcat(ticket_buffer, "|");
        strcat(ticket_buffer, scan_list->arrival_time);
        strcat(ticket_buffer, "|");
        strcat(ticket_buffer, scan_list->train_number);
        strcat(ticket_buffer, "|");
        strcat(ticket_buffer, scan_list->type1_price);
        strcat(ticket_buffer, "|");
        strcat(ticket_buffer, scan_list->type2_price);
        strcat(ticket_buffer, "|");
        strcat(ticket_buffer, scan_list->type3_price);
        strcat(ticket_buffer, "|");
        strcat(ticket_buffer, scan_list->type4_price);
        strcat(ticket_buffer, "|");
        strcat(ticket_buffer, scan_list->date);
        strcat(ticket_buffer, "|");
        strcat(ticket_buffer, scan_list->ticket_type1_num);
        strcat(ticket_buffer, "|");
        strcat(ticket_buffer, scan_list->ticket_type2_num);
        strcat(ticket_buffer, "|");
        strcat(ticket_buffer, scan_list->ticket_type3_num);
        strcat(ticket_buffer, "|");
        strcat(ticket_buffer, scan_list->ticket_type4_num);
        strcat(ticket_buffer, "|");
        strcat(ticket_buffer, ",");
    }
    strcat(ticket_buffer, ".");
    return true;
}

/**
 * @brief   车票链表销毁
 * @param   ticket_head:包含所有车票信息的指针
 *          user_ticket_head:包含所有用户的车票信息的指针
 * @return  true:正常运行
 *          false:读取文件失败
 */
int ticket_destroy(struct list_head *ticket_head,
                    struct list_head *user_ticket_head)
{
    struct list_head *ticket_pos, *user_ticket_pos, *n, *m;
    struct ticket *ticket_free;
    struct user_ticket *user_ticket_free;
    int ret;

    ret = write_ticket_file(ticket_head);
    if (ret != true) {
        DEBUG("WRITE TICKET FILE ERROR!");
        return false;
    }
    ret = write_user_ticket_file(user_ticket_head);
    if (ret != true) {
        DEBUG("WRITE USER TICKET FILE ERROR!");
        return false;
    }

    list_for_each_safe (ticket_pos, n, ticket_head) {
        list_del(ticket_pos);
        ticket_free = list_entry(ticket_pos, struct ticket, list);
        free(ticket_free);
    }

    list_for_each_safe (user_ticket_pos, m, user_ticket_head) {
        list_del(user_ticket_pos);
        user_ticket_free = list_entry(user_ticket_pos,
                                        struct user_ticket, list);
        free(user_ticket_free);
    }

    return true;
}

/**
 * @brief   将车票数据写入文件中
 * @param   ticket_head：车票数据的头指针
 * @return  传参错误、打开文件错误返回false
 *          正确运行返回true
 */
static int write_ticket_file(struct list_head *ticket_head)
{
    if (!ticket_head) {
        DEBUG("PARAM ERROR\n");
        return false;
    }

    struct ticket *scan_list;
    struct list_head *pos;
    FILE *save_file;

    /* 打开文件 */
    save_file = fopen("./lib/ticket_data.txt", "w");
    if (!save_file) {
        save_file = fopen("../.././lib/ticket_data.txt", "w");
        if (!save_file) {
            DEBUG("FAIL TO OPEN TICKET DATA FILE\n");
            return false;
        }
    }

    /* 将链表中的数据依次写入文件 */
    list_for_each (pos, ticket_head) {
        scan_list = list_entry(pos, struct ticket, list);
        fprintf(save_file, "%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\n",
                            scan_list->origin_place,
                            scan_list->destination,
                            scan_list->train_number,
                            scan_list->departure_time,
                            scan_list->arrival_time, 
                            scan_list->type1_price,
                            scan_list->type2_price,
                            scan_list->type3_price,
                            scan_list->type4_price,
                            scan_list->date,
                            scan_list->ticket_type1_num,
                            scan_list->ticket_type2_num,
                            scan_list->ticket_type3_num,
                            scan_list->ticket_type4_num);
    }

    fclose(save_file);
    return true; 
}

/**
 * @brief   将车票数据写入文件中
 * @param   ticket_head：车票数据的头指针
 * @return  传参错误、打开文件错误返回false
 *          正确运行返回true
 */
static int write_user_ticket_file(struct list_head *user_ticket_head)
{
    if (!user_ticket_head) {
        DEBUG("PARAM ERROR\n");
        return false;
    }

    struct user_ticket *scan_list;
    struct list_head *pos;
    FILE *save_file;

    /* 打开文件 */
    save_file = fopen("./lib/user_ticket_data.txt", "w");
    if (!save_file) {
        save_file = fopen("../.././lib/user_ticket_data.txt", "w");
        if (!save_file) {
            DEBUG("FAIL TO OPEN TICKET DATA FILE\n");
            return false;
        }
    }

    /* 将链表中的数据依次写入文件 */
    list_for_each (pos, user_ticket_head) {
        scan_list = list_entry(pos, struct user_ticket, list);
        fprintf(save_file, "%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\n",
                            scan_list->id,
                            scan_list->name,
                            scan_list->citizen_id,
                            scan_list->phone_num,
                            scan_list->origin_place, 
                            scan_list->destination,
                            scan_list->train_number,
                            scan_list->departure_time,
                            scan_list->arrival_time,
                            scan_list->price,
                            scan_list->date,
                            scan_list->ticket_type);
    }

    fclose(save_file);
    return true; 
}

/* 获取系统日期 */
static void get_date(char *date)
{
    struct tm *t;
    time_t tt;
    time(&tt);
    t = localtime(&tt);
    sprintf(date, "%4d-%02d-%02d", t->tm_year + 1900, t->tm_mon + 1, t->tm_mday);
}

/* 比较日期 */
static int compare_date(char *date1, char *date2)
{
    int year1_int, year2_int, month1_int, month2_int, day1_int, day2_int;
    char year1[5] = {0}, month1[3] = {0}, day1[3] = {0};
    char year2[5] = {0}, month2[3] = {0}, day2[3] = {0};
    struct tm tt, tt2;

    strncpy(year1, date1, 4);
    strncpy(month1, date1 + 5, 2);
    strncpy(day1, date1 + 8, 2);
    
    strncpy(year2, date2, 4);
    strncpy(month2, date2 + 5, 2);
    strncpy(day2, date2 + 8, 2);

    year1[4] = '\0';
    month1[2] = '\0';
    day1[2] = '\0';
    year2[4] = '\0';
    month2[2] = '\0';
    day2[2] = '\0';
    
    year1_int = atoi(year1);
    month1_int = atoi(month1);
    day1_int = atoi(day1);

    year2_int = atoi(year2);
    month2_int = atoi(month2);
    day2_int = atoi(day2);

    memset(&tt, 0, sizeof(tt));
    tt.tm_year = year1_int - 1900;
    tt.tm_mon = month1_int - 1;
    tt.tm_mday = day1_int;
    tt.tm_hour = 0;
    tt.tm_min = 0;
    tt.tm_sec = 0;
    
    memset(&tt2, 0, sizeof(tt2));
    tt2.tm_year = year2_int - 1900;
    tt2.tm_mon = month2_int - 1;
    tt2.tm_mday = day2_int;
    tt2.tm_hour = 0;
    tt2.tm_min = 0;
    tt2.tm_sec = 0;

    if (mktime(&tt) >= mktime(&tt2)) {
	    return 1;
    } else {
    	return 0;
    }
}

/* 比较车站信息 */
int compare_ticket(char *ticket1, char *ticket2)
{
    int ticket1_len, ticket2_len;
    char tmp_ticket1[20] = {0}, tmp_ticket2[20] = {0};
    char tmp1[4] = {0}, tmp2[4] = {0};

    ticket1_len = strlen(ticket1);
    ticket2_len = strlen(ticket2);

    /*将最后一个字抽取出来（东南西北）*/
    memcpy(tmp1, ticket1 + (ticket1_len - 3), 3);
    memcpy(tmp2, ticket2 + (ticket2_len - 3), 3);
    tmp1[3] = '\0';
    tmp2[3] = '\0';

    /*  1.乐昌东 乐昌东
        2.乐昌东 乐昌
        3.乐昌 乐昌东
        4.乐昌 乐昌*/
    if (0 == strcmp(tmp1, "东") ||
        0 == strcmp(tmp1, "南") ||
        0 == strcmp(tmp1, "西") ||
        0 == strcmp(tmp1, "北")) {
        if (0 == strcmp(tmp2, "东") ||
            0 == strcmp(tmp2, "南") ||
            0 == strcmp(tmp2, "西") ||
            0 == strcmp(tmp2, "北")) {
            /* 去掉后面的东南西北 */
            memcpy(tmp_ticket1, ticket1, ticket1_len - 3);
            memcpy(tmp_ticket2, ticket2, ticket2_len - 3);
            if (0 == strcmp(tmp_ticket1, tmp_ticket2)) {
                return 0;
            } else {
                return 1;
            }
        } else {
            /* 去掉后面的东南西北 */
            memcpy(tmp_ticket1, ticket1, ticket1_len - 3);
            if (0 == strcmp(tmp_ticket1, ticket2)) {
                return 0;
            } else {
                return 1;
            }
        }
        
    } else {
        if (0 == strcmp(tmp2, "东") ||
            0 == strcmp(tmp2, "南") ||
            0 == strcmp(tmp2, "西") ||
            0 == strcmp(tmp2, "北")) {
            /* 去掉后面的东南西北 */
            memcpy(tmp_ticket2, ticket2, ticket2_len - 3);
            if (0 == strcmp(ticket1, tmp_ticket2)) {
                return 0;
            } else {
                return 1;
            }
        } else {
            if (0 == strcmp(ticket1, ticket2)) {
                return 0;
            } else {
                return 1;
            }
        }
    }
}
